(function(){
    // 定义一个表示人的类
    // TS 可以在属性前添加属性的修饰符
    /**
     * public 修饰的属性可以在任意位置访问（修改）默认值
     *    - 如果不加修饰符，默认就是public
     *    - 子类中也可以访问（修改）
     * private 私有属性，私有属性只能在类内部进行访问（修改）
     *    - 通过在类中添加方法使得私有属性可以被外部访问
     * protected 受保护的属性，只能在当前类和当前类的子类中访问（修改）
     * */ 
    class Person {
        private _name: string;
        private _age: number;
        constructor(name: string, age: number) {
            this._name = name;
            this._age = age;
        }

        /**
         * getter 方法用来读取属性
         * setter 方法用来设置属性
         *   - 它们被称为属性的存取器
         * 
         * */ 
        // 定义一个方法，用来获取name属性
        getName() {
            return this._name;
        }
        // 定义一个方法，用来设置name属性
        setName(value: string) {
            this._name = value;
        }
        getAge() {
            return this._age;
        }
        setAge(value: number) {
            if (value >= 0) {
                this._age = value;
            }
        }

        // TS 中设置getter方法的方式
        get name() {
            return this._name;
        }
        // TS 中设置setter方法的方式
        set name(value: string) {
            this._name = value;
        }
        get age() {
            return this._age;
        }
        set age(value: number) {
            if (value >= 0) {
                this._age = value;
            }
        }
    }

    const per = new Person('孙悟空', 18);
    console.log(per);

    /**
     * 
     * 现在属性是在对象中设置的，属性可以任意的被更改
     *   属性可以任意被更改将会导致对象中的数据变得非常不安全
     * */ 
    // per.name = '猪八戒';
    // per.age = 28;
    // console.log(per);

    // per.setName('猪八戒');
    // per.setAge(-28);
    // console.log(per);


    per.name = '猪八戒';
    per.age = 28;
    console.log(per);


    class A {
        protected num: number;
        constructor(num: number) {
            this.num = num;
        }
    }
    class B extends A {
        test() {
            console.log(this.num);
        }
    }

    const b = new B(456);
    // console.log(b.num); // err: Property 'num' is protected and only accessible within class 'A' and its subclasses.
    b.test();

    /**
     * 语法糖
     *   - TS 可以在构造函数中直接将属性定义在构造函数中
     * */ 
    class C {
        // 可以直接将属性定义在构造函数中
        constructor(public name: string, public age: number) {
            this.name = name;
            this.age = age;
        }
    }
    const c = new C('tom', 18);
    console.log(c);

})();